package il.ac.tau.cvws.scrabblesidekick.server.engine.scrabble.detector;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import il.ac.tau.cvws.scrabblesidekick.server.engine.dictionary.exception.DictionaryException;
import il.ac.tau.cvws.scrabblesidekick.server.util.exception.ExceptionConstant;
import il.ac.tau.cvws.scrabblesidekick.server.util.exception.ScrabbleSidekickException;
import il.ac.tau.cvws.scrabblesidekick.shared.constant.BoardConstants;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.WordPlacement;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Direction;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Position;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.Rack;
import il.ac.tau.cvws.scrabblesidekick.shared.datatype.game.TileLayout;

public class VerticalSolutionDetector extends SolutionDetector
{
	@Override	
	/*
	 * LOGIC: The function search for the valid vertical results for the current layout on board and user's rack. The function uses the given dictionary from DB to find these words.
	 * 		  First of all the function finds the maximal column and the minimal column by iterating over the layout boundries points.
	 * 		  Next, the function iterate each column (between the minimal and maximal column found before) and define a length for a pattern from 2 to 15. 
	 * 		  Then, the function iterate over each cell on column and search for a template in the predeined length, where a template must consist at least one tile non-empty. 
	 * 		  when the function finds such template it calls findSolution that retrieve the right solution (as explained there) and validate each retrieved answer by calling validateSolution. 
	 * INPUT:layoutBoundries- all points that have at least one free cell in adjacent to them a, layout-  Set of all existing tiles on board,  dictionaryId- identifier of language in DB, rack - user's rack
	 * RETURN: the function return all vertical suggestion for the current rack and layout.
	 */
	public List<WordPlacement> detect(Set<Position> layoutBoundries, TileLayout layout, int dictionaryId,Rack rack) throws ScrabbleSidekickException 
	{
		int minCol = Integer.MAX_VALUE;
		int maxCol = 0;
		List<WordPlacement> solList = new ArrayList<WordPlacement>();
		
		boolean isLeft2Right = false;
		
		try
		{
			isLeft2Right = dbEngine.isLeft2RightDictionary(dictionaryId);
		}
		catch (SQLException e)
		{
			throw new DictionaryException(ExceptionConstant.GENERAL_FAILURE);
		} 

		for (Position p : layoutBoundries)
		{
			if (p.getColumn() < minCol)
			{
				minCol = p.getColumn();
			}

			if (p.getColumn() > maxCol)
			{
				maxCol = p.getColumn();
			}
		}

		for (int i = minCol; i < maxCol; i++)
		{
			for (int currWidth =  BoardConstants.BOARD_TILES_NUM ; currWidth >= 2 ; currWidth--)
			{
				for (int j = 0; j + currWidth <= BoardConstants.BOARD_TILES_NUM; j++)
				{
					Set<Position> positions = layout.asPostitionSet();
					boolean exist = false;
					
					for (Position p: positions)
					{
						if ((j <= p.getRow()) && (p.getRow() < j + currWidth) && (p.getColumn() == i))
						{
							exist = true; 
							break;
						}
					}

					if (exist)
					{
						Position startPos = new Position(j , i);
						List<Integer> wordTemplate = createWordTemplate(layout, startPos, currWidth, Direction.VERTICAL);

						List<int[]> possibleSolutions = findSolutions(rack, wordTemplate, dictionaryId);

						if (possibleSolutions.size() == 0)
						{
							continue;
						}
						else
						{
							for (int[] sol : possibleSolutions)
							{	
								if (validateSolution(sol, layout, startPos, currWidth, Direction.VERTICAL,dictionaryId,isLeft2Right))
								{
									solList.add( new WordPlacement(layout.asIndices(), sol,startPos,Direction.VERTICAL));
								}					
							}
						}
					}
				}
			}
		}

		return solList;
	}
}
